package com.demo.socketchannel;

import com.alibaba.fastjson.JSON;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;

/**
 * @author MT
 * @date 2019-12-10 10:28
 */
public class SocketChannelClient {
    private Selector selector;
    private SocketChannel socketChannel;

    private ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
    private ByteBuffer readBuffer = ByteBuffer.allocate(1024);

    public SocketChannelClient(String hostname, int port) {
        try {
            // 创建SocketChannel 监听8081端口
            socketChannel = SocketChannel.open();
            // 设置为非阻塞
            socketChannel.configureBlocking(false);
            socketChannel.connect(new InetSocketAddress(hostname, port));

            selector = Selector.open();
            //Channel注册到selector上，必需在非阻塞模式下
            socketChannel.register(selector, SelectionKey.OP_CONNECT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 发送消息
    private void sendMsg(String msg) throws IOException {
        // 清空缓冲区
        writeBuffer.clear();
        // 将要发送的消息提交到缓冲区
        writeBuffer.put(msg.getBytes("UTF-8"));
        // 翻转缓冲区:该限制设置为当前位置，然后将该位置设置为零。 如果标记被定义，则它被丢弃。
        //在通道读取或放置操作的序列之后，调用此方法来准备一系列通道写入或相对获取操作
        writeBuffer.flip();
        // 如果还有剩余，一直写入
        while (writeBuffer.hasRemaining()) {
            socketChannel.write(writeBuffer);
        }
        // 清空缓冲区
        writeBuffer.clear();
        // 压缩此缓冲区,以防后续写入数据不完整，从缓冲区写入数据之后调用此方法
        writeBuffer.compact();
    }

    // 接收读取消息
    private void readMsg() throws IOException {
        if (socketChannel.read(readBuffer) == -1) {
            System.out.println("没有返回消息");
            return;
        }
        //改写入为读取
        readBuffer.flip();
        String receivedRequestData = Charset.forName("UTF-8").newDecoder().decode(readBuffer).toString();
        readBuffer.clear();
        Result returnResult = JSON.parseObject(receivedRequestData, Result.class);
        if (returnResult != null) {
            System.out.println(returnResult.toString());
        } else {
            System.out.println("没有返回消息");
        }
    }

    // 关闭socket
    private void close() throws IOException {
        socketChannel.close();
    }

    public static void main(String[] args) throws IOException {
        SocketChannelClient socketChannelClient = new SocketChannelClient("192.168.1.163", 8081);
        // 需要发送的数据
        Result result = Result.getInstance();
        result.setCode(1);
        result.setData("测试");
        result.setSuccess(true);
        result.setMsg("测试JSON连接");

        // 如果连接已完成
        if (socketChannelClient.socketChannel.finishConnect()) {
            int i = 0;
            while(true){

                result.setCode(i);
                // 将对象转为json字符串
                String message = JSON.toJSONString(result);

                socketChannelClient.sendMsg(message);

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                socketChannelClient.readMsg();
                i++;
            }
        }
    }
}